package edu.xlh.travel.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alipay.api.AlipayApiException;
import edu.xlh.travel.common.Result;
import edu.xlh.travel.dao.*;
import edu.xlh.travel.enumeration.*;
import edu.xlh.travel.pojo.*;
import edu.xlh.travel.pojo.querypojo.QueryCheckTask;
import edu.xlh.travel.service.*;
import edu.xlh.travel.util.DateTimeUtil;
import edu.xlh.travel.util.DoubleChaineUpdateStatus;
import edu.xlh.travel.util.IdWorker;

import edu.xlh.travel.util.PageResult;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.*;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;

@Service
@Transactional
public class CheckingTaskServiceImpl implements CheckingTaskService {
    @Autowired
    private CheckingTaskDao checkingTaskDao;
    @Autowired
    private CheckedTaskService checkedTaskService;
    @Autowired
    private OrdersService ordersService;
    @Autowired
    private ScenicService scenicService;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    private CallBackService callBackService;
    @Autowired
    private ForeHotelOrderService foreHotelOrderService;
    @Autowired
    private HotelService hotelService;
    @Autowired
    private CheckedTaskDao checkedTaskDao;
    @Autowired
    private ForeHotelOrderDao foreHotelOrderDao;
    @Autowired
    private HotelDao hotelDao;
    @Autowired
    private EmailDao emailDao;
    @Autowired
    private DoubleChaineUpdateStatus doubleChaineUpdateStatus;

    @Override
    public Result drawback(String orderId, String orderType , HttpSession session) {
        System.out.println("订单种类："+orderType);
        User user = (User) session.getAttribute("user");
        if (user == null) {
            return new Result(201, "会话过期，请重新登录");
        }
        //修改订单状态为退款申请中
        try {
            if (OrderTypeEnum.scenicOrder.getCode().equals(orderType)) {
                ordersService.updateStatusByOrderId(OrderStatusEnum.drawbackApllying.getCode(), orderId);
            } else {
                foreHotelOrderService.updateStatusByHotelOrderId(OrderStatusEnum.drawbackApllying.getCode(), orderId);
            }
        } catch (Exception e) {
            return new Result(3, "退款申请提交成功,订单状态修改失败");
        }
        //获取当前时间
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date = df.format(new Date());// new Date()为获取当前系统时间，也可使用当前时间戳
        Date stringDate = DateTimeUtil.strToDate(date, "yyyy-MM-dd HH:mm:ss");
        CheckingTask checkingTask = new CheckingTask().setId(idWorker.nextId() + "")
                .setOrderId(orderId)
                .setUserId(user.getId())
                .setCreateTime(stringDate)
                .setModifyTime(stringDate)
                .setDelFlag("0")
                .setOrderType(orderType)
                .setBusinessType(CheckBusinessTypeEnum.drawback.getCode())
                .setBusinessDesc(CheckBusinessTypeEnum.drawback.getDesc());
        CheckingTask save = checkingTaskDao.save(checkingTask);
        if (save != null) {
            return new Result(200, "退款申请提交成功");
        }
        return new Result(202, "退款申请提交失败");
    }

    @Override
    public Result findAllCheckingTask(int page, int limit , HttpSession session) {
        User user = (User)session.getAttribute("admin");
        if (user == null) {
            return new Result(201,"会话过期，请重新登陆");
        }
        //查询没有审核过和没有被取消的记录
        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> checkingTask = new ArrayList<>();
                checkingTask.add(criteriaBuilder.equal(root.get("delFlag"), "0"));
                if ("3".equals(user.getPerm())) {
                    checkingTask.add(criteriaBuilder.equal(root.get("orderType"), "1"));
                } else if ("2".equals(user.getPerm())) {
                    checkingTask.add(criteriaBuilder.equal(root.get("orderType"), "0"));
                }
                return criteriaBuilder.and(checkingTask.toArray(new Predicate[checkingTask.size()]));
            }
        };
        Sort sort = Sort.by(Sort.Direction.DESC, "createTime");
        Pageable pageable= PageRequest.of(page-1,limit ,sort);
        Page<CheckingTask> checkingTaskPage = checkingTaskDao.findAll(specification, pageable);
        if (checkingTaskPage!=null) {
            return new Result(0 , "待审核任务分页数据获取成功" , new PageResult<CheckingTask>(checkingTaskPage.getTotalElements(), checkingTaskPage.getContent()));
        }
        return new Result(201, "返回待审核任务列表失败或者暂时没有待审核任务");
    }

    @Override
    public Result agree(CheckingTask checkingTask, HttpSession session) {
        User user = (User) session.getAttribute("admin");
        if (user == null) {
            return new Result(201, "会话过期，请重新登录");
        }
        if (!CheckBusinessTypeEnum.cancel.getCode().equals(checkingTask.getBusinessType())
        &&!CheckBusinessTypeEnum.hotelConsumeApplyinig.getCode().equals(checkingTask.getBusinessType())) {
            //异步退款
            CompletableFuture<Void> storeCaptchaToRedis = CompletableFuture.runAsync(()->{
                try {
                    String result = callBackService.refund(checkingTask.getOrderId());
                } catch (AlipayApiException e) {
                    System.out.println(e.getErrMsg());
                }
            },threadPoolTaskExecutor);
        }

        //获取当前时间
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date = df.format(new Date());// new Date()为获取当前系统时间，也可使用当前时间戳
        Date stringDate = DateTimeUtil.strToDate(date, "yyyy-MM-dd HH:mm:ss");
        //软删除待审核任务记录
        checkingTask.setModifyTime(stringDate).setDelFlag("1");
        checkingTaskDao.updateCheckingTaskDelFlagByCheckingTaskId(checkingTask.getId() , "1");
        //新增已审核任务记录
        String orderType = checkingTask.getOrderType();
        CheckedTask checkedTask = new CheckedTask().setId(idWorker.nextId() + "")
                .setOrderId(checkingTask.getOrderId())
                .setUserId(checkingTask.getUserId())
                .setCreateTime(stringDate)
                .setModifyTime(stringDate)
                .setBusinessType(checkingTask.getBusinessType())
                .setBusinessDesc(checkingTask.getBusinessDesc())
                .setDelFlag("0")
                .setCheckerId(user.getId())
                .setCheckResultType(CheckResultTypeEnum.agree.getCode())
                .setCheckResultDesc(CheckResultTypeEnum.agree.getDesc())
                .setOrderType("0".equals(orderType) ? "0" : "1");
        CheckedTask save = checkedTaskService.save(checkedTask);
        //修改订单表状态
        if (OrderTypeEnum.scenicOrder.getCode().equals(orderType)) {
                ordersService.updateStatusByOrderId(CheckBusinessTypeEnum.cancel.getCode().equals(checkingTask.getBusinessType())? OrderStatusEnum.cancelApllyingSuccess.getCode():OrderStatusEnum.drawbackApllyingSuccess.getCode()
                        , checkingTask.getOrderId());
                Orders orders = ordersService.findById(checkingTask.getOrderId());
                Scenic scenic = scenicService.findByScenicId(orders.getScenicId());
                //修改商品库存数量
                ordersService.updateStockByOrderId(checkingTask.getOrderId(), scenic.getStock() + orders.getQty());
        } else {
            if (CheckBusinessTypeEnum.hotelConsumeApplyinig.getCode().equals(checkingTask.getBusinessType())) {
                String orderId = checkingTask.getOrderId();
                Hotel_orders hotel_orders = foreHotelOrderDao.findById(orderId).get();
                Hotel hotel = hotelDao.findById(hotel_orders.getScenicId()).get();

                //同步母子订单状态
                doubleChaineUpdateStatus.syncHotelOrder(hotel_orders , OrderStatusEnum.hotelConsuming.getCode());

                foreHotelOrderDao.updateStockByHotelOrderId(orderId , hotel_orders.getQty() + hotel.getStock());
                Email email = new Email()
                        .setId(idWorker.nextId() + "")
                        .setOrderId(hotel_orders.getId())
                        .setSendOutUserId(user.getId())
                        .setSendOutName(user.getName())
                        .setReceiveUserId(hotel_orders.getUserId())
                        .setReceiveName(hotel_orders.getUserName())
                        .setSendTime(new Date())
                        .setIsRead("0")
                        .setDelFlag("0")
                        .setEmailType(EmailTypeEnum.checkOutSuccess.getCode())
                        .setOrderType(OrderTypeEnum.hotelOrder.getCode());
                emailDao.save(email);
            } else {
                foreHotelOrderService.updateStatusByHotelOrderId(CheckBusinessTypeEnum.cancel.getCode().equals(checkingTask.getBusinessType())? OrderStatusEnum.cancelApllyingSuccess.getCode():OrderStatusEnum.drawbackApllyingSuccess.getCode()
                        , checkingTask.getOrderId());
                Hotel_orders hotel_orders = foreHotelOrderService.findById(checkingTask.getOrderId());
                Hotel hotel = hotelService.findByHotelId(hotel_orders.getScenicId());
                //修改商品库存数量
                foreHotelOrderService.updateStockByHotelOrderId(checkingTask.getOrderId(), hotel.getStock() + hotel_orders.getQty());
            }
        }
        if (save != null) {
            return new Result(200, "审核成功，同意申请");
        }
        return new Result(202, "审核失败");
    }

    @Override
    public Result reject(CheckingTask checkingTask, HttpSession session) {
        User user = (User) session.getAttribute("admin");
        if (user == null) {
            return new Result(201, "会话过期，请重新登录");
        }
        //获取当前时间
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date = df.format(new Date());// new Date()为获取当前系统时间，也可使用当前时间戳
        Date stringDate = DateTimeUtil.strToDate(date, "yyyy-MM-dd HH:mm:ss");
        //软删除待审核任务记录
        checkingTask.setModifyTime(stringDate).setDelFlag("1");
        checkingTaskDao.updateCheckingTaskDelFlagByCheckingTaskId(checkingTask.getId() , "1");
        //新增已审核任务记录
        String orderType = checkingTask.getOrderType();
        CheckedTask checkedTask = new CheckedTask().setId(idWorker.nextId() + "")
                .setOrderId(checkingTask.getOrderId())
                .setUserId(checkingTask.getUserId())
                .setCreateTime(stringDate)
                .setModifyTime(stringDate)
                .setBusinessType(checkingTask.getBusinessType())
                .setBusinessDesc(checkingTask.getBusinessDesc())
                .setDelFlag("0")
                .setCheckerId(user.getId())
                .setCheckResultType(CheckResultTypeEnum.reject.getCode())
                .setCheckResultDesc(CheckResultTypeEnum.reject.getDesc())
                .setOrderType("0".equals(orderType) ? "0" : "1");;

        CheckedTask save = checkedTaskService.save(checkedTask);
        //修改订单表状
        if (OrderTypeEnum.scenicOrder.getCode().equals(orderType)) {
                ordersService.updateStatusByOrderId(OrderStatusEnum.drawbackApllyingFail.getCode()
                        , checkingTask.getOrderId());

        } else {
            if (CheckBusinessTypeEnum.hotelConsumeApplyinig.getCode().equals(checkingTask.getBusinessType())) {
                String orderId = checkingTask.getOrderId();
                foreHotelOrderDao.updateStatusByHotelOrderId(OrderStatusEnum.hotelConsumeApplyinigFail.getCode(), orderId);
            } else {
                foreHotelOrderService.updateStatusByHotelOrderId(OrderStatusEnum.drawbackApllyingFail.getCode()
                        , checkingTask.getOrderId());
            }
        }
        if (save != null) {
            return new Result(200, "审核成功，拒绝申请");
        }
        return new Result(202, "审核失败");
    }

    @Override
    public Result cancelOrder(String orderId ,String orderType , HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user == null) {
            return new Result(201, "用户登录信息过期，请重新登录");
        }
        //修改订单状态为退款申请中
        try {
            if ("1".equals(orderType)) {
                ordersService.updateStatusByOrderId(OrderStatusEnum.cancelApllying.getCode(), orderId);
            } else {
                foreHotelOrderService.updateStatusByHotelOrderId(OrderStatusEnum.cancelApllying.getCode(), orderId);
            }
        } catch (Exception e) {
            return new Result(3, "取消订单申请提交成功,订单状态修改失败");
        }
        //获取当前时间
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date = df.format(new Date());// new Date()为获取当前系统时间，也可使用当前时间戳
        Date stringDate = DateTimeUtil.strToDate(date, "yyyy-MM-dd HH:mm:ss");
        CheckingTask checkingTask = new CheckingTask().setId(idWorker.nextId() + "")
                .setOrderId(orderId)
                .setUserId(user.getId())
                .setCreateTime(stringDate)
                .setModifyTime(stringDate)
                .setDelFlag("0")
                .setBusinessType(CheckBusinessTypeEnum.cancel.getCode())
                .setBusinessDesc(CheckBusinessTypeEnum.cancel.getDesc())
                .setOrderType(orderType);
        CheckingTask save = checkingTaskDao.save(checkingTask);
        if (save != null) {
            return new Result(200, "取消订单申请提交成功");
        }
        return new Result(202, "取消订单申请提交失败");
    }

    @Override
    public Result QueryCheckingTaskByCondition(Integer page, Integer limit, QueryCheckTask queryCheckingTask, HttpSession session) {
        User userFromSession = (User)session.getAttribute("admin");
        if (userFromSession == null) {
            return new Result(201,"会话过期，请重新登陆");
        }

        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> checkingTaskList = new ArrayList<>();
                if (StringUtils.isNotEmpty(queryCheckingTask.getId())) {
                    checkingTaskList.add(criteriaBuilder.equal(root.get("id") , queryCheckingTask.getId()));
                }
                if (StringUtils.isNotEmpty(queryCheckingTask.getOrderId())) {
                    checkingTaskList.add(criteriaBuilder.equal(root.get("orderId") , queryCheckingTask.getOrderId()));
                }
                if (StringUtils.isNotEmpty(queryCheckingTask.getBusinessType())) {
                    checkingTaskList.add(criteriaBuilder.equal(root.get("businessType") , queryCheckingTask.getBusinessType()));
                }
                if (queryCheckingTask.getCreateTime() != null) {
                    String crateTime = DateTimeUtil.dateToStr(queryCheckingTask.getCreateTime(), "yyyy-MM-dd");
                    String crateTimeStartTimeToStr = crateTime + " " + "00:00:00";
                    String crateTimeEndTimeToStr = crateTime + " " + "23:59:59";
                    Date crateTimeStartTimeToDate = DateTimeUtil.strToDate(crateTimeStartTimeToStr , "yyyy-MM-dd HH:mm:ss");
                    Date crateTimeEndTimeToDate = DateTimeUtil.strToDate(crateTimeEndTimeToStr , "yyyy-MM-dd HH:mm:ss");
                    checkingTaskList.add(criteriaBuilder.between(root.get("createTime") ,  crateTimeStartTimeToDate , crateTimeEndTimeToDate));
                }
                if (queryCheckingTask.getModifyTime() != null) {
                    String modifyTime = DateTimeUtil.dateToStr(queryCheckingTask.getModifyTime(), "yyyy-MM-dd");
                    String modifyTimeStartTimeToStr = modifyTime + " " + "00:00:00";
                    String modifyTimeEndTimeToStr = modifyTime + " " + "23:59:59";
                    Date modifyTimeStartTimeToDate = DateTimeUtil.strToDate(modifyTimeStartTimeToStr , "yyyy-MM-dd HH:mm:ss");
                    Date modifyTimeEndTimeToDate = DateTimeUtil.strToDate(modifyTimeEndTimeToStr , "yyyy-MM-dd HH:mm:ss");

                    checkingTaskList.add(criteriaBuilder.between(root.get("modifyTime") ,  modifyTimeStartTimeToDate , modifyTimeEndTimeToDate));
                }
                checkingTaskList.add(criteriaBuilder.equal(root.get("delFlag") ,"0"));
                return criteriaBuilder.and(checkingTaskList.toArray(new Predicate[checkingTaskList.size()]));
            }
        };
        Pageable pageable= PageRequest.of(page-1,limit);
        Page<CheckingTask> checkingTaskListPage  = checkingTaskDao.findAll(specification , pageable);
        if (checkingTaskListPage!=null) {
            return new Result(0 , "待审核列表分页数据获取成功" , new PageResult<CheckingTask>(checkingTaskListPage.getTotalElements(), checkingTaskListPage.getContent()));
        }
        return new Result(201 , "待审核列表列表失败");
    }

    //传标志，共用接口
    @Override
    public Result deleteById(String id, HashMap hashMap, HttpSession session) {
        User user = (User)session.getAttribute("admin");
        if (user == null) {
            return new Result(201,"会话过期，请重新登陆");
        }
        String taskId = (String) hashMap.get("id");
        String taskType = (String) hashMap.get("taskType");
        String orderId = (String) hashMap.get("orderId");
        if (id.equals(taskId)) {
            if ("0".equals(taskType)) {
                try {
                    checkingTaskDao.updateCheckingTaskDelFlagByCheckingTaskId(taskId , "1");
                    checkedTaskDao.updateCheckedTaskDelFlagByOrderId(orderId , "1");
                } catch (Exception e) {
                    return new Result(201 , "id为"+taskId+"的待审核记录和对应的已审核记录"+"删除失败");
                }
            } else if ("1".equals(taskType)) {
                try {
                    checkedTaskDao.updateCheckedTaskDelFlagByCheckedTaskId(taskId , "1");
                    checkingTaskDao.updateCheckingTaskDelFlagByOrderId (orderId , "1");
                } catch (Exception e) {
                    return new Result(201 , "id为"+taskId+"的已审核记录和对应的待审核记录"+"删除失败");
                }
            }
        } else {
            return new Result(202 , "id为"+taskId+"的公告id有问题");
        }
        if ("0".equals(taskType)) {
            return new Result(200 , "id为"+taskId+"的待审核记录和对应的已审核记录"+"删除成功");
        }
        return new Result(200 , "id为"+taskId+"的已审核记录和对应的待审核记录"+"删除成功");
    }

    @Override
    public Result batchDelete(JSONArray jsonArray, String taskType, HttpSession session) {
        if ("0".equals(taskType)) {
            List<CheckingTask> checkingTaskList = JSON.parseArray(jsonArray.toJSONString() , CheckingTask.class);
            try {
                checkingTaskList.stream().iterator().forEachRemaining(checkingTask -> {
                    checkingTaskDao.updateCheckingTaskDelFlagByCheckingTaskId(checkingTask.getId() , "1");
                    checkedTaskDao.updateCheckedTaskDelFlagByOrderId(checkingTask.getOrderId() , "1");
                });
            }catch (Exception e) {
                return new Result(201);
            }
        }  else if ("1".equals(taskType)) {
            List<CheckedTask> checkedTaskList = JSON.parseArray(jsonArray.toJSONString() , CheckedTask.class);
            try {
                checkedTaskList.stream().iterator().forEachRemaining(checkedTask -> {
                    checkedTaskDao.updateCheckedTaskDelFlagByCheckedTaskId(checkedTask.getId() , "1");
                    checkingTaskDao.updateCheckingTaskDelFlagByOrderId(checkedTask.getOrderId() , "1");
                });
            }catch (Exception e) {
                return new Result(201);
            }
        }  else {

        }
        if ("0".equals(taskType)) {
            return new Result(200 , "批量待审核记录和对应的已审核记录"+"删除成功");
        }
        return new Result(200 , "批量已审核记录和对应的待审核记录"+"删除成功");
    }

    @Override
    public Result checkOut(String orderId, HttpSession session) {
      /*  User userFromSession = (User)session.getAttribute("user");
        if (userFromSession == null) {
            return new Result(201,"会话过期，请重新登陆");
        }
        try {
            Hotel_orders hotel_orders = foreHotelOrderDao.findById(orderId).get();
            Hotel hotel = hotelDao.findById(hotel_orders.getScenicId()).get();
            foreHotelOrderDao.updateStatusByHotelOrderId(OrderStatusEnum.hotelConsuming.getCode(), orderId);
            foreHotelOrderDao.updateStockByHotelOrderId(orderId , hotel_orders.getQty() + hotel.getStock());
        }catch (Exception e) {
            return new Result(202 , "退房失败");
        }
        return new Result(200 , "退房成功");*/

        User user = (User) session.getAttribute("user");
        if (user == null) {
            return new Result(201, "会话过期，请重新登录");
        }
        //修改订单状态为退房申请中
        try {
                Hotel_orders hotel_orders = foreHotelOrderService.findById(orderId);
                //同步母子订单状态
                doubleChaineUpdateStatus.syncHotelOrder(hotel_orders , OrderStatusEnum.hotelConsumeApplyinig.getCode());
                /*foreHotelOrderService.updateStatusByHotelOrderId(OrderStatusEnum.hotelConsumeApplyinig.getCode(),orderId );*/
        } catch (Exception e) {
            return new Result(3, "退款申请提交成功,订单状态修改失败");
        }
        //获取当前时间
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date = df.format(new Date());// new Date()为获取当前系统时间，也可使用当前时间戳
        Date stringDate = DateTimeUtil.strToDate(date, "yyyy-MM-dd HH:mm:ss");
        CheckingTask checkingTask = new CheckingTask().setId(idWorker.nextId() + "")
                .setOrderId(orderId)
                .setUserId(user.getId())
                .setCreateTime(stringDate)
                .setModifyTime(stringDate)
                .setDelFlag("0")
                .setOrderType(OrderTypeEnum.hotelOrder.getCode())
                .setBusinessType(CheckBusinessTypeEnum.hotelConsumeApplyinig.getCode())
                .setBusinessDesc(CheckBusinessTypeEnum.hotelConsumeApplyinig.getDesc());
        CheckingTask save = checkingTaskDao.save(checkingTask);
        if (save != null) {
            return new Result(200, "退房申请提交成功");
        }
        return new Result(202, "退房申请提交失败");
    }

}
